using Nemerle.Collections;
using Nextem.String;

using Microcosm.Common;

namespace Microcosm.Server {
	[Record(Include=[places, renderables, isMultiUser, startLocation, defaultAvatarModel])]
	[CosmClass]
	public class Place {
		places : list [Place];
		renderables : list [Renderable];
		isMultiUser : bool;
		startLocation : (float * float * float) * (float * float * float);
		defaultAvatarModel : Model;
		avatars : Hashtable [int, (float * float * float) * (float * float * float)] = Hashtable();
		
		cosmProperty(0) Places : list [Place] { get { places } }
		cosmProperty(1) Renderables : list [Renderable] { get { renderables } }
		cosmProperty(2) IsMultiUser : bool { get { isMultiUser } }
		cosmEvent(3) event AvatarUpdate : CosmEventHandler [int * ((float * float * float) * (float * float * float))];
		cosmProperty(4) StartLocation : (float * float * float) * (float * float * float) { get { startLocation } }
		
		cosmMethod(5) Enter(viewer : Viewer) : void {
			def avatar = viewer.Avatar;
			def ((x, y, z), (rx, ry, rz)) = startLocation;
			avatars[avatar.AvatarId] = ((-x, -y, -z), (-rx, -ry, -rz));
			unless(AvatarUpdate == null)
				AvatarUpdate(avatar.AvatarId, avatars[avatar.AvatarId]);
			avatar.PositionUpdate += 
				fun(pos : float * float * float, orient : float * float * float) {
					avatars[avatar.AvatarId] = (pos, orient);
					unless(AvatarUpdate == null)
						AvatarUpdate(avatar.AvatarId, (pos, orient))
				}
		}
		
		cosmProperty(6) Avatars : list [int * ((float * float * float) * (float * float * float))] {
			get {
				avatars.Fold(
					[], 
					fun(key, val, acc) {
						(key, val) :: acc
					}
				)
			}
		}
		cosmProperty(7) DefaultAvatarModel : Model { get { defaultAvatarModel } }
	}
}
